package com.ruoyi.api.user;

import java.io.BufferedReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.api.cache.ICacheService;
import com.ruoyi.api.config.MyWxConfig;
import com.ruoyi.api.user.requestVo.UserWxLoginRequestVo;
import com.ruoyi.api.user.requestVo.UserWxPayRequestVo;
import com.ruoyi.api.util.DateUtil;
import com.ruoyi.api.util.JWTUtil;
import com.ruoyi.api.util.wx.AuthUtil;
import com.ruoyi.api.util.wx.DownloadPicFromURL;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.framework.web.base.BaseController;
import com.ruoyi.payment.wxpay.WXPay;
import com.ruoyi.payment.wxpay.WXPayUtil;
import com.ruoyi.user.domain.Order;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.service.IOrderService;
import com.ruoyi.user.service.IUserService;

import io.swagger.annotations.ApiOperation;

/**
 * APP微信授权操作处理
 * @author ruoyi
 * @date 2018-12-14
 */
@Controller
@RequestMapping("/api/wx")
public class ApiWxController extends BaseController
{
	
	private static final Logger log = LoggerFactory.getLogger(ApiWxController.class);
	
    private String prefix = "api:wx";
	
	@Autowired
	private IUserService userService;
	
	@Autowired
	private ICacheService cacheService;
	
	@Autowired
	private IOrderService orderService;
	
	
	/**
	 * 用户微信授权登录
	 * @return
	 */
	@Log(title = "APP微信授权登录", businessType = BusinessType.LOGIN)
	@PostMapping("/login")
	@ResponseBody
	@ApiOperation(value="APP微信授权登录", notes="APP微信授权登录",produces = "application/json")
	public HashMap<String, Object> login(HttpServletRequest request,@RequestBody UserWxLoginRequestVo loginRequestVo)
	{
		try {
			String code = loginRequestVo.getCode();
			/*String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + AuthUtil.APPID + "&secret="
					+ AuthUtil.APPSECRET + "&code=" + code + "&grant_type=authorization_code";*/
			/*JSONObject jsonObject = AuthUtil.doGetJson(url);*/
			String response = HttpUtils.sendGet("https://api.weixin.qq.com/sns/oauth2/access_token", "appid=" + AuthUtil.APPID + "&secret="
					+ AuthUtil.APPSECRET + "&code=" + code + "&grant_type=authorization_code");
			JSONObject jsonObject = (JSONObject) JSONObject.parse(response);
			String openid = jsonObject.getString("openid");
			String token = jsonObject.getString("access_token");
			if(token==null||"".equals(token)){
				return errorApp("wx-0001", jsonObject.getString("errmsg"));
			}
			/*String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + token + "&openid=" + openid
					+ "&lang=zh_CN";*/
			String response1 = HttpUtils.sendGet("https://api.weixin.qq.com/sns/userinfo", "access_token=" + token + "&openid=" + openid
					+ "&lang=zh_CN");
			/*JSONObject userInfo = AuthUtil.doGetJson(infoUrl);*/
			JSONObject userInfo = (JSONObject) JSONObject.parse(response1);
			System.out.println(userInfo);
			String unionid = userInfo.getString("unionid");
			String sex = userInfo.getString("sex");
			String nickname = userInfo.getString("nickname");
			String headimgurl = userInfo.getString("headimgurl");
			String headPic = null;
			if(token==null||"".equals(token)){
				return errorApp("wx-0001", userInfo.getString("errmsg"));
			}
			if(headimgurl!=null&&!"".equals(headimgurl)){
				headPic = DownloadPicFromURL.downloadPicture(headimgurl);
			}
			return loginTo(unionid, openid, sex, nickname, headPic);
			// 2、将微信与当前系统的账号进行绑定
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return errorApp("wx-0001", "微信授权失败");
		}
	}
	
	public HashMap<String, Object> loginTo(String unionid,String openid,String sex,String nickname,String headPic){
		String result_str = "";
		User param = new User();
		param.setOpenid(openid);
		param.setSource(1);
		List<User> userList = userService.selectUserList(param);
		if(userList!=null&&userList.size()>0){
			User userCurrent = userList.get(0);
			String subject = openid;
			cacheService.put("ry-user-id",subject,userCurrent.getId());
			String jwtToken = JWTUtil.createToken(subject);
			cacheService.put("ry-user-token",subject,jwtToken);
			result_str = "Bearer:" + jwtToken;
		}else{
			User user = new User();
			user.setAccount(openid);
			user.setNickName(nickname);
			user.setStatus(1);
			user.setCreateTime(new Date());
			user.setIsVip(0);
			user.setUnionid(unionid);
			user.setOpenid(openid);
			user.setHeadPic("app/img/"+headPic);
			user.setSource(1);
			if(sex!=null&&!"".equals(sex)){
				user.setSex(Integer.valueOf(sex));
			}
			userService.insertUser(user);
			User param1 = new User();
			param1.setOpenid(openid);
			param1.setSource(1);
			List<User> userList1 = userService.selectUserList(param1);
			if(userList1!=null&&userList1.size()>0){
				String subject = openid;
				cacheService.put("ry-user-id",subject,userList1.get(0).getId());
				String jwtToken = JWTUtil.createToken(subject);
				cacheService.put("ry-user-token",subject,jwtToken);
				result_str = "Bearer:" + jwtToken;
			}
		}
		return successApp(result_str);
	}
	
	/**
     * 微信统一下单接口
     * @return
     */
	@ResponseBody
	@PostMapping("/doOrder")
	@ApiOperation(value="微信统一下单接口", notes="微信统一下单接口",produces = "application/json")
    public Map<String, Object> doOrder(HttpServletRequest request, @RequestBody UserWxPayRequestVo payRequestVo) {
		LinkedHashMap<String,String> resultMap=new LinkedHashMap<String,String>();
        MyWxConfig config = null;
        WXPay wxpay =null;
        try {
            config = new MyWxConfig();
            wxpay= new WXPay(config);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //生成的随机字符串
        String nonce_str = WXPayUtil.generateNonceStr();
        //获取客户端的ip地址
        //获取本机的ip地址
        InetAddress addr = null;
        try {
            addr = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String spbill_create_ip = addr.getHostAddress();
        //支付金额，需要转成字符串类型，否则后面的签名会失败
        int  total_fee = payRequestVo.getAmount();
        //商品描述
        String body = payRequestVo.getContent();
        //商户订单号
        /*String out_trade_no= WXPayUtil.generateNonceStr();*/
        String out_trade_no= DateUtil.genOrderNum();
        //统一下单接口参数
        LinkedHashMap<String, String> data = new LinkedHashMap<String, String>();
        data.put("appid", config.getAppID());
        data.put("mch_id", config.getMchID());
        data.put("nonce_str", nonce_str);
        data.put("sign_type", "MD5");
        data.put("body", "安+平台-会员充值");
        data.put("detail", body);
        data.put("out_trade_no",out_trade_no);
        data.put("total_fee", String.valueOf(total_fee));
        data.put("spbill_create_ip", spbill_create_ip);
        //data.put("notify_url", "http://47.52.113.233/api/wx/payNotifyUrl");
        data.put("notify_url", "http://47.93.23.253:8090/api/wx/payNotifyUrl");
        data.put("trade_type","APP");
        try {
			String signParam = WXPayUtil.generateSignature(data, config.getKey());
			data.put("sign", signParam);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
        try {
            Map<String, String> rMap = wxpay.unifiedOrder(data);
            System.out.println("统一下单接口返回: " + rMap);
            String return_code = (String) rMap.get("return_code");
            String result_code = (String) rMap.get("result_code");
            
            Long timeStamp = System.currentTimeMillis() / 1000;
            if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
            	//再次签名，这个签名用于小程序端调用wx.requesetPayment方法
            	Order order = new Order();
            	User user = (User) request.getAttribute("user");
            	order.setContent(body);
            	order.setMonths(payRequestVo.getMonths());
            	order.setAmount(payRequestVo.getAmount());
            	order.setCreateTime(new Date());
            	order.setOrderNum(out_trade_no);
            	order.setStatus(1);
            	order.setTpye(1);
            	order.setUserId(user.getId());
            	String prepayid = rMap.get("prepay_id");
            	order.setPayid(prepayid);
            	order.setTtype(payRequestVo.getType());
            	orderService.insertOrder(order);
                resultMap.put("appid",config.getAppID());
                resultMap.put("partnerid", config.getMchID());
            	resultMap.put("prepayid", prepayid);
            	resultMap.put("package", "Sign=WXPay");
            	String nonceStr = WXPayUtil.generateNonceStr();
                resultMap.put("noncestr", nonceStr);
                resultMap.put("timestamp", timeStamp + "");
                /*resultMap.put("signType", "MD5");*/
                //这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                String sign = WXPayUtil.generateSignature(resultMap, config.getKey());
                resultMap.put("sign", sign);
                System.out.println("生成的签名paySign : "+ sign);
                return successApp(resultMap);
            }else{
            	return errorApp("wx-0003",(String) rMap.get("return_msg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return errorApp("wx-0002", "微信预生产订单失败");
        }
    }
    
    @ResponseBody
	@PostMapping("/payNotifyUrl")
	@ApiOperation(value="微信支付异步结果通知", notes="微信支付异步结果通知",produces = "application/json")
    public HashMap<String, String> payNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	HashMap<String,String> resultMap=new HashMap<String,String>();
    	BufferedReader reader = null;

        reader = request.getReader();
        String line = "";
        String xmlString = null;
        StringBuffer inputString = new StringBuffer();

        while ((line = reader.readLine()) != null) {
            inputString.append(line);
        }
        xmlString = inputString.toString();
        request.getReader().close();
        System.out.println("----接收到的数据如下：---" + xmlString);
        Map<String, String> map = WXPayUtil.xmlToMap(xmlString);
        String result_code = map.get("result_code");
        String out_trade_no = map.get("out_trade_no");
        String return_code = map.get("return_code");
        MyWxConfig config = null;
        WXPay wxpay =null;
        try {
            config = new MyWxConfig();
            wxpay= new WXPay(config);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (wxpay.isPayResultNotifySignatureValid(map)) {
        	// 签名正确
            // 进行处理。
        	Order param = new Order();
        	param.setOrderNum(out_trade_no);
        	param.setStatus(1);
        	List<Order> list = orderService.selectOrderList(param);
        	if(list!=null&&list.size()>0){
        		Order order = list.get(0);
        		order.setStatus(2);
        		orderService.updateOrder(order);
        		User user = userService.selectUserById(order.getUserId());
        		if(user!=null){
        			if(user.getIsVip()!=null&&user.getIsVip()!=1){
        				user.setIsVip(1);
        				user.setVipType(order.getTtype());
        				user.setVipTime(DateUtil.addMonthsToDate(new Date(), order.getMonths()));
        			}else{
        				user.setVipType(order.getTtype());
        				user.setVipTime(DateUtil.addMonthsToDate(user.getVipTime(), order.getMonths()));
        			}
        			userService.updateUser(user);
        		}
        		resultMap.put("return_code", "SUCCESS");
        		resultMap.put("return_msg", "OK");
        	}
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
        } else {
        	// 签名错误，如果数据里没有sign字段，也认为是签名错误
        	Order param = new Order();
        	param.setOrderNum(out_trade_no);
        	List<Order> list = orderService.selectOrderList(param);
        	if(list!=null&&list.size()>0){
        		Order order = list.get(0);
        		order.setStatus(3);
        		orderService.updateOrder(order);
        	}
        	resultMap.put("return_code", "ERROR");
    		resultMap.put("return_msg", "NULL");
        }
        return resultMap;
    }

}
